{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -*- coding: utf-8 -*-\n",
    "from keras.preprocessing import image              #加载包\n",
    "import cv2\n",
    "import keras\n",
    "from keras import backend as K\n",
    "from keras.models import load_model\n",
    "#from PIL import Image\n",
    "import numpy as np\n",
    "\n",
    "from keras.models import Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(28, 28, 1)\n"
     ]
    }
   ],
   "source": [
    "#第一步：加载测试图片\n",
    "img_path = \"./4-1.png\"                                  #测试图片路径\n",
    "img = image.load_img(img_path,target_size=(28,28))      #cv2加载测试图片reshape\n",
    "img = img.convert('L')                                  #测试图片转为灰度值\n",
    "\n",
    "x = image.img_to_array(img)             #图像数据转为数组\n",
    "print(x.shape)                          #打印图像的维度尺寸\n",
    "x = np.expand_dims(x, axis=0)           #图像周围补0\n",
    "x=x.astype('float32')/255.              #图像像素归一化\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_1\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_1 (Conv2D)            (None, 28, 28, 16)        160       \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 14, 14, 16)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 14, 14, 32)        4640      \n",
      "_________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2 (None, 7, 7, 32)          0         \n",
      "_________________________________________________________________\n",
      "flatten_1 (Flatten)          (None, 1568)              0         \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 1568)              0         \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 128)               200832    \n",
      "_________________________________________________________________\n",
      "dropout_2 (Dropout)          (None, 128)               0         \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 10)                1290      \n",
      "=================================================================\n",
      "Total params: 206,922\n",
      "Trainable params: 206,922\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "9\n",
      "[<keras.layers.convolutional.Conv2D object at 0x7f79159d41d0>, <keras.layers.pooling.MaxPooling2D object at 0x7f79159d4390>, <keras.layers.convolutional.Conv2D object at 0x7f7915e53cf8>, <keras.layers.pooling.MaxPooling2D object at 0x7f79155ad7f0>, <keras.layers.core.Flatten object at 0x7f79155ad4a8>, <keras.layers.core.Dropout object at 0x7f79155ada90>, <keras.layers.core.Dense object at 0x7f79155add68>, <keras.layers.core.Dropout object at 0x7f79159bf668>, <keras.layers.core.Dense object at 0x7f79159bf438>]\n"
     ]
    }
   ],
   "source": [
    "#第二步：导入已经训练的模型\n",
    "model=keras.models.load_model('./model1.h5')\n",
    "#模型概括打印\n",
    "print(\"模型概括：\")\n",
    "model.summary()\n",
    "#模型的层数\n",
    "print(\"网络层数：\",len(model.layers))\n",
    "#模型包括的层名词\n",
    "print(\"每一层的名称：\",model.layers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "#第三步，将模型作为一个层，输出第0层的输出\n",
    "layer_model = Model(inputs=model.input, outputs=model.layers[0].output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "float32\n",
      "(1, 28, 28, 16)\n",
      "<class 'numpy.ndarray'>\n",
      "(16, 1, 28, 28)\n",
      "索引值：0.0000000\n",
      "[[[[0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   ...\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]]]\n",
      "\n",
      "\n",
      " [[[0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   ...\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]]]\n",
      "\n",
      "\n",
      " [[[0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   ...\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]]]\n",
      "\n",
      "\n",
      " ...\n",
      "\n",
      "\n",
      " [[[0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   ...\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]]]\n",
      "\n",
      "\n",
      " [[[0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   ...\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]]]\n",
      "\n",
      "\n",
      " [[[0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   ...\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]\n",
      "   [0. 0. 0. ... 0. 0. 0.]]]]\n"
     ]
    }
   ],
   "source": [
    "#第四步，调用新建的层模型的predict方法，得到模型的输出\n",
    "feature=layer_model.predict(x)\n",
    "print(feature.dtype)                 #打印输出特征图\n",
    "print(feature.shape)           #打印输出特征图的形状\n",
    "print(type(feature))           #打印输出特征图的数据类型\n",
    "\n",
    "feature=feature.transpose(3,0,1,2)          #转置\n",
    "print(feature.shape)\n",
    "print(\"索引值：{0:.7f}\".format(feature[0,0,0,4]))\n",
    "print(feature.astype(\"float32\"))                 #打印转置后的输出特征图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n",
      "/usr/local/python3/lib/python3.7/site-packages/tensorflow/python/framework/dtypes.py:526: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "/usr/local/python3/lib/python3.7/site-packages/tensorflow/python/framework/dtypes.py:527: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "/usr/local/python3/lib/python3.7/site-packages/tensorflow/python/framework/dtypes.py:528: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "/usr/local/python3/lib/python3.7/site-packages/tensorflow/python/framework/dtypes.py:529: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "/usr/local/python3/lib/python3.7/site-packages/tensorflow/python/framework/dtypes.py:530: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "/usr/local/python3/lib/python3.7/site-packages/tensorflow/python/framework/dtypes.py:535: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /usr/local/python3/lib/python3.7/site-packages/tensorflow/python/ops/resource_variable_ops.py:435: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n",
      "WARNING:tensorflow:From /usr/local/python3/lib/python3.7/site-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.cast instead.\n",
      "conv1层输出原本的形状： (1, 28, 28, 16)\n",
      "conv1层输出转置后的形状： (16, 1, 28, 28)\n",
      "12544\n",
      "提取conv1输出\n"
     ]
    }
   ],
   "source": [
    "#方法二===============================================================================================================================\n",
    "# -*- coding: utf-8 -*-\n",
    "from keras.preprocessing import image\n",
    "import cv2\n",
    "from keras import backend as K\n",
    "from keras.models import load_model\n",
    "#from PIL import Image\n",
    "import numpy as np\n",
    "\n",
    "def get_layer_output(model, x, index=-1):\n",
    "    \"\"\"\n",
    "    get the computing result output of any layer you want, default the last layer.\n",
    "    :param model: primary model\n",
    "    :param x: input of primary model( x of model.predict([x])[0])\n",
    "    :param index: index of target layer, i.e., layer[23]\n",
    "    :return: result\n",
    "    \"\"\"\n",
    "    layer = K.function([model.input], [model.layers[index].output])\n",
    "    return layer([x])[0]\n",
    "\n",
    "model = load_model('./model1.h5')              #导入训练好的模型\n",
    "img_path = \"./4-1.png\"                         #导入测试图片\n",
    "img = image.load_img(img_path,target_size=(28,28))      \n",
    "img = img.convert('L')                         #测试图片转为灰度值\n",
    "\n",
    "x = image.img_to_array(img)                    #\n",
    "x = np.expand_dims(x, axis=0)\n",
    "input_x=x.astype('float32')/255.\n",
    "conv1 = get_layer_output(model, input_x, index=0)         #提取conv1层的输出\n",
    "print(\"conv1层输出原本的形状：\",conv1.shape)\n",
    "#print(conv1)\n",
    "#conv_1=conv1.reshape(16,1,28,28)\n",
    "conv_1=conv1.transpose(3,0,1,2)\n",
    "print(\"conv1层输出转置后的形状：\",conv_1.shape)\n",
    "print(conv_1.size)\n",
    "#print(conv_1)\n",
    "conv_1.tofile('./layer_out/conv1.txt', sep=' ',format='%f')\n",
    "print(\"提取conv1输出\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 14, 14, 16)\n",
      "(16, 1, 14, 14)\n",
      "3136\n",
      "提取pool1输出\n"
     ]
    }
   ],
   "source": [
    "pool1 = get_layer_output(model, input_x, index=1)\n",
    "print(pool1.shape)\n",
    "#print(pool1)\n",
    "\n",
    "pool_1=pool1.transpose(3,0,1,2)\n",
    "print(pool_1.shape)\n",
    "print(pool_1.size)\n",
    "pool_1.tofile('./layer_out//pool1.txt', sep=' ',format='%f')\n",
    "#print(pool_1)\n",
    "print(\"提取pool1输出\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 14, 14, 32)\n",
      "(32, 1, 14, 14)\n",
      "6272\n",
      "提取conv2输出\n"
     ]
    }
   ],
   "source": [
    "conv2 = get_layer_output(model, input_x, index=2)\n",
    "print(conv2.shape)\n",
    "conv_2=conv2.transpose(3,0,1,2)\n",
    "print(conv_2.shape)\n",
    "print(conv_2.size)\n",
    "conv_2.tofile('./layer_out//conv2.txt', sep=' ',format='%f')\n",
    "print(\"提取conv2输出\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 7, 7, 32)\n",
      "(32, 1, 7, 7)\n",
      "1568\n",
      "提取pool2输出\n"
     ]
    }
   ],
   "source": [
    "pool2 = get_layer_output(model, input_x, index=3)\n",
    "print(pool2.shape)\n",
    "pool_2=pool2.transpose(3,0,1,2)\n",
    "print(pool_2.shape)\n",
    "print(pool_2.size)\n",
    "pool_2.tofile('./layer_out//pool2.txt', sep=' ',format='%f')\n",
    "print(\"提取pool2输出\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 1568)\n",
      "1568\n",
      "提取flatten1输出\n"
     ]
    }
   ],
   "source": [
    "flatten1 = get_layer_output(model, input_x, index=4)\n",
    "print(flatten1.shape)\n",
    "print(flatten1.size)\n",
    "flatten1.tofile('./layer_out//flatten.txt', sep=' ',format='%f')\n",
    "print(\"提取flatten1输出\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 128)\n",
      "<class 'numpy.ndarray'>\n",
      "128\n",
      "提取fc1输出\n"
     ]
    }
   ],
   "source": [
    "fc1 = get_layer_output(model, input_x, index=6)\n",
    "print(fc1.shape)\n",
    "print(type(fc1))\n",
    "print(fc1.size)\n",
    "fc1.tofile('./layer_out//fc1.txt', sep=' ',format='%f')\n",
    "print(\"提取fc1输出\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 10)\n",
      "10\n",
      "提取fc2输出\n",
      "[[5.2318823e-14 1.3150577e-04 6.0465538e-08 2.3893253e-14 9.9985194e-01\n",
      "  1.5161897e-13 9.1620738e-09 1.6353997e-05 4.3253381e-10 1.5114437e-12]]\n",
      "5.2318823e-14\n",
      "<class 'numpy.float32'>\n"
     ]
    }
   ],
   "source": [
    "fc2 = get_layer_output(model, input_x, index=8)\n",
    "print(fc2.shape)\n",
    "print(fc2.size)\n",
    "fc2.tofile('./layer_out//fc2.txt', sep=' ',format='%f')\n",
    "print(\"提取fc2输出\")\n",
    "print(fc2)     #输出最后的结果\n",
    "print(fc2[0][0])     #输出最后的结果\n",
    "print(type(fc2[0][0]))    #输出最后的结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
